<?php 
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.5.1 / SVN信息: $Id: class.Process.php 2211 2009-12-26 06:34:29Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/

namespace JCAT\PDRL\MultiTask ;


use JCAT\PDRL\MultiTask;
use JCAT\Core\Assert;

class Process
{
    /**
     * Description
     *
     * @access	public
     * @static
     * @return	Process
     */
	static public function CreateChildProcess($sCmd,$sCWD=null,$nFlags=0)
    {    	
    	$aInput = Pipe::Create() ;
    	$aOurput = Pipe::Create() ;
    	$aError = Pipe::Create() ;
    	
    	$aProcess = self::CreateProcess(
    			$sCmd
    			, $aInput->GetReadHandle()		// child proc STD Input
    			, $aOurput->GetWriteHandle()	// child proc STD Output
    			, $aError->GetWriteHandle()		// child proc STD Error
    			, $nFlags, $sCWD
    	) ;
    	if(!$aProcess)
    	{
    		return null ;
    	}
    	
    	$aProcess->SetPipe($aInput,STD_INPUT_HANDLE) ;
    	$aProcess->SetPipe($aOurput,STD_OUTPUT_HANDLE) ;
    	$aProcess->SetPipe($aError,STD_ERROR_HANDLE) ;
    	return $aProcess ;
    }

    /**
     * Description
     *
     * @access	public
     * @static
     * @return	Process
     */
    static public function CreatePHPProcess($sScriptFile,array $arrParams=array(),$sCWD=null,$nFlags=0)
    { 
    	$sPhpPath = pdr_get_php_path() ;
    	foreach ($arrParams as $key=>&$sParam)
    	{
    		$sParam = trim($sParam) ;
    		if( $sParam==='' or $sParam===null )
    		{
    			unset($arrParams[$key]) ;
    		}
    		else 
    		{
    			$sParam = '"'.addslashes($sParam).'"' ;
    		}
    	}
    	$sCmdParams = ' '.implode(' ',$arrParams) ;
    	
    	echo $sCmd = "\"{$sPhpPath}\" \"{$sScriptFile}\"{$sCmdParams}" ;
    	return self::CreateChildProcess($sCmd,$sCWD,$nFlags) ;
    }

    /**
     * Description
     *
     * @access	public
     * @static
     * @return	Process
     */
    static public function CreateParentProcess()
    {    	
    	$aInput = new Pipe() ;
    	$aInput->SetWriteHandle(pdr_pipe_get_std(STD_OUTPUT_HANDLE)) ;
    	$aOurput = new Pipe() ;
    	$aOurput->SetReadHandle(pdr_pipe_get_std(STD_INPUT_HANDLE)) ;
    	
    	$sClassName = get_called_class() ;
    	$aProcess = new $sClassName() ;
    	
    	$aProcess->SetPipe($aInput,STD_INPUT_HANDLE) ;
    	$aProcess->SetPipe($aOurput,STD_OUTPUT_HANDLE) ;
    	return $aProcess ;
    }
    
    /**
     * Description
     *
     * @access	protected
     * @static
     * @return	Process
     */
    static protected function CreateProcess($sCmd,$nInput=0,$nOutput=0,$nError=0,$nFlags=0,$sCWD=null)
    {
    	if(!$sCWD)
    	{
    		$sCWD = getcwd() ;
    	}
    	
    	$hProcess = pdr_proc_create('',$sCmd,$sCWD,true,$nInput,$nOutput,$nError,$nFlags) ;
    	$sClassName = get_called_class() ;
    	return $hProcess? new $sClassName($hProcess): null ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @param	$hProcess
     * @return	void
     */
    public function Process($hProcess=null)
    {
    	if($hProcess)
    	{
	    	Assert\IS_R($hProcess) ;
	    	$this->hProcess = $hProcess ;
    	}
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	handle
     */
    public function GetResource()
    {
    	return $this->hProcess ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @param	$aPipe		Pipe
     * @return	void
     */
    public function SetPipe(Pipe $aPipe,$nType)
    {
    	if(array_key_exists($nType,$this->arrPipes))
    	{
    		$this->arrPipes[$nType] = $aPipe ;
    	}
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	\JCAT\PDRL\MultiTask\Pipe
     */
    public function GetInputPipe()
    {
    	return $this->arrPipes[STD_INPUT_HANDLE] ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	\JCAT\PDRL\MultiTask\Pipe
     */
    public function GetOutputPipe()
    {
    	return $this->arrPipes[STD_OUTPUT_HANDLE] ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @param	$Parameter
     * @return	\JCAT\PDRL\MultiTask\Pipe
     */
    public function GetErrorPipe()
    {
    	return $this->arrPipes[STD_ERROR_HANDLE] ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	handle
     */
    public function GetProcessHandle()
    {
    	if(!$this->hProcess)
    	{
    		return null ;
    	}
    	
    	return pdr_proc_get_handle($this->hProcess) ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	handle
     */
    public function GetMainThreadHandle()
    {
    	if(!$this->hProcess)
    	{
    		return null ;
    	}
    	
    	return pdr_proc_get_tread_handle($this->hProcess) ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	int
     */
    public function GetExitCode()
    {
    	return pdr_proc_exit_code( $this->GetProcessHandle() ) ;
    }
    
    /**
     * 关闭进程。
     * 
     *
     * @access	public
     * @return	bool
     */
    public function Terminate($nExitCode=0)
    {
    	return $this->GetResource()?
    		pdr_proc_terminate( $this->GetProcessHandle(), $nExitCode ): false ;
    }
    
    /**
     * Description
     *
     * @access	public
     * @return	bool
     */
    public function IsAlive()
    {
    	if( !$hHandle=$this->GetProcessHandle() )
    	{
    		return false ;
    	}
    	return pdr_proc_exit_code($hHandle)==STILL_ACTIVE  ;
    }
    
    /**
     * Description
     * 
     * @access	private
     * @var		handle
     */
    private $hProcess ;
    
    /**
     * Description
     * 
     * @access	private
     * @var		array
     */
    private $arrPipes = array(
    	STD_INPUT_HANDLE => null ,
    	STD_OUTPUT_HANDLE => null ,
    	STD_ERROR_HANDLE => null ,
    ) ;

}

?>